Marginal plots

Author

Andrés Devegili

Marginal plots live on the “margins” of a main plot, adding extra information about the X and Y variables. In the example below, the marginals show how each group is distributed along each axis, complementing the relationships in the main scatter plot.


Layouts

Marginal plots an be placed in different positions around the main plot. They may appear on one side or on two sides, most often above (x-axis) and to the right (y-axis). You can also add layers, stacking multiple plot types on the same margin for richer context.

The main plot should always be the star

Marginal plots are there to provide secondary context, not to steal the spotlight.


Inventory

Marginal plots come in many forms. Histograms, boxplots, density curves, strip plots, and violins are common choices, though almost any plot type can be used. When you add more than one marginal, they can either match (same type) or be mixed (different types) to enrich the story. You can also layer them to add even more context.

More isn’t always better

Adding too many marginals can clutter your plot and overwhelm the reader.


How to build marginal plots

Two recipes in Python and R.

Python (Seaborn, jointplot)

import seaborn as sns
import matplotlib.pyplot as plt

# Dataset
tips = sns.load_dataset("tips")

# MAIN + MARGINAL PLOTS
g = sns.jointplot(
    data=tips, x="total_bill", y="tip",
    kind="scatter", height=6, marginal_ticks=True,
    joint_kws={"s": 80, "alpha": 0.8}
)
sns.set_theme(style="white")

plt.subplots_adjust(top=0.9)

# Title (main + subtitle)
plt.suptitle(
    "Relationship between total bill and tip.\n"
    "With marginal histograms showing distributions.", 
    fontsize=14, y=1
)

_ = g.set_axis_labels("Total bill (USD)", "Tip (USD)", labelpad=10)

# Optional: Tidy marginals
for ax in (g.ax_marg_x, g.ax_marg_y):
    _ = sns.despine(ax=ax, top=True, right=True, left=True, bottom=True)
    ax.tick_params(left=False, labelleft=False, bottom=False, labelbottom=False)

plt.show()

R (ggplot2+ggExtra)

library(ggplot2)
library(ggExtra)

# Main ggplot scatter
p2 <- ggplot(mtcars, aes(x = mpg, y = wt)) +
  geom_point(color = "darkgreen", size = 4, alpha = 0.6)+
  theme_classic()+
  labs(
    x = "Miles per gallon (mpg)",
    y = "Weight (1000 lbs)",
    title = "Fuel efficiency vs. vehicle weight",
    subtitle = "With marginal densities"
  )

# Add MARGINAL PLOTS
ggMarginal(p2, type = "density", fill = "lightgreen", color = "darkgreen", alpha = 0.5)


Packages

Python Seaborn | Matplotlib

R ggplot2 | ggExtra


2025 · GitHub · AndresDeve